
package org.androbuzz;

import java.util.ArrayList;
import java.util.HashMap;

import android.accounts.Account;
//import android.accounts.AccountManager;
import android.accounts.OperationCanceledException;
import android.app.Service;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.RawContacts.Entity;
import android.util.Log;

/**
 * @author Arnaud Dupuis <a.dupuis@infinityperl.org>
 * 
 */
public class AndroBuzzSyncProviderContactsSyncAdapterService extends Service {
	private static final String TAG = "AndroBuzzSyncProviderContactsSyncAdapterService";
	private static SyncAdapterImpl sSyncAdapter = null;
	private static ContentResolver mContentResolver = null;

	public AndroBuzzSyncProviderContactsSyncAdapterService() {
		super();
	}

	private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
		private Context mContext;

		public SyncAdapterImpl(Context context) {
			super(context, true);
			mContext = context;
		}

		@Override
		public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
			try {
				AndroBuzzSyncProviderContactsSyncAdapterService.performSync(mContext, account, extras, authority, provider, syncResult);
			} catch (OperationCanceledException e) {
			}
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		IBinder ret = null;
		ret = getSyncAdapter().getSyncAdapterBinder();
		return ret;
	}

	private SyncAdapterImpl getSyncAdapter() {
		if (sSyncAdapter == null)
			sSyncAdapter = new SyncAdapterImpl(this);
		return sSyncAdapter;
	}

	private static void addContact(Account account, String name, String username) {
		Log.i(TAG, "Adding contact: " + name);
		ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();

		ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
		builder.withValue(RawContacts.ACCOUNT_NAME, account.name);
		builder.withValue(RawContacts.ACCOUNT_TYPE, account.type);
		builder.withValue(RawContacts.SYNC1, username);
		operationList.add(builder.build());

		builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
		builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0);
		builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
		builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name);
		operationList.add(builder.build());

		builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
		builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
		builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.androbuzz.SyncProviderProfile");
		builder.withValue(ContactsContract.Data.DATA1, username);
		builder.withValue(ContactsContract.Data.DATA2, "AndroBuzz SyncProvider Profile");
		builder.withValue(ContactsContract.Data.DATA3, "View profile");
		operationList.add(builder.build());

		try {
			mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static void updateContactStatus(ArrayList<ContentProviderOperation> operationList, long rawContactId, String status) {
		Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
		Uri entityUri = Uri.withAppendedPath(rawContactUri, Entity.CONTENT_DIRECTORY);
		Cursor c = mContentResolver.query(entityUri, new String[] { RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1 }, null, null, null);
		try {
			while (c.moveToNext()) {
				if (!c.isNull(1)) {
					String mimeType = c.getString(2);

					if (mimeType.equals("vnd.android.cursor.item/vnd.org.androbuzz.SyncProviderProfile")) {
						ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(ContactsContract.StatusUpdates.CONTENT_URI);
						builder.withValue(ContactsContract.StatusUpdates.DATA_ID, c.getLong(1));
						builder.withValue(ContactsContract.StatusUpdates.STATUS, status);
						builder.withValue(ContactsContract.StatusUpdates.STATUS_RES_PACKAGE, "org.androbuzz");
						builder.withValue(ContactsContract.StatusUpdates.STATUS_LABEL, R.string.app_name);
						builder.withValue(ContactsContract.StatusUpdates.STATUS_ICON, R.drawable.icon);
						builder.withValue(ContactsContract.StatusUpdates.STATUS_TIMESTAMP, System.currentTimeMillis());
						operationList.add(builder.build());

						builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);
						builder.withSelection(BaseColumns._ID + " = '" + c.getLong(1) + "'", null);
						builder.withValue(ContactsContract.Data.DATA3, status);
						operationList.add(builder.build());
					}
				}
			}
		} finally {
			c.close();
		}
	}

	private static void performSync(Context context, Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult)
			throws OperationCanceledException {
		Log.i(TAG, "======================================== performSync START ======================================== ");
		HashMap<String, Long> localContacts = new HashMap<String, Long>();
		mContentResolver = context.getContentResolver();
		Log.i(TAG, "performSync: " + account.toString());

		// Load the local contacts
		Uri rawContactUri = RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name).appendQueryParameter(
				RawContacts.ACCOUNT_TYPE, account.type).build();
		Cursor c1 = mContentResolver.query(rawContactUri, new String[] { BaseColumns._ID, RawContacts.SYNC1 }, null, null, null);
		while (c1.moveToNext()) {
			Log.i(TAG, "AndroBuzz performSync: add to localContacts => " + c1.getString(1));
			localContacts.put(c1.getString(1), c1.getLong(0));
		}
		c1.close();
		ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
		AndroBuzzDbAdapter adapter = new AndroBuzzDbAdapter(context);
		adapter.open();
		try {
			Cursor c = adapter.getAllBuddies();
			// If we don't have any contacts, create one. Otherwise, set a
			// status message
			do {
				String user_name = c.getString(c.getColumnIndex( AndroBuzzDbAdapter.KEY_BUDDIES_NAME ));
				String user_mail = c.getString(c.getColumnIndex( AndroBuzzDbAdapter.KEY_BUDDIES_EMAIL ));
				String user_id = user_mail;
				if( user_mail.endsWith("@gmail.com") ){
					user_id = user_mail.replace("@gmail.com","");
				}
				Log.i(TAG, "AndroBuzz performSync: user => " + user_name + " id => " + user_id);
				if (localContacts.get(user_id) == null) {
					addContact(account, user_name, user_id);
				}else{
					Cursor cr = adapter.fetchAllBuzzes(user_id);
					String bs = cr.getString( cr.getColumnIndex(AndroBuzzDbAdapter.KEY_SUMMARY));
					Log.i(TAG, "AndroBuzz performSync: last buzz summary is => " + bs);
					updateContactStatus(operationList, localContacts.get(user_id), bs);
				}
			}while (c.moveToNext());
			
//			if (localContacts.get("arnaud.l.dupuis") == null) {
//				addContact(account, "Arnaud DUPUIS", "arnaud.l.dupuis");
//			} else {
//				updateContactStatus(operationList, localContacts.get("arnaud.l.dupuis"), "AndroBuzz Sync Provider is working quite well !!");
//			}
//			if (localContacts.get("androbuzz") == null) {
//				addContact(account, "AndroBuzz", "androbuzz");
//			} else {
//				updateContactStatus(operationList, localContacts.get("androbuzz"), "AndroBuzz Sync Provider is also working for me !");
//			}
			if (operationList.size() > 0)
				mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}
}
